/* 验证规则定义 */
/**
 * @widoc $.validator
 * @namespace aux
 * @des 验证规则接口。若定义了 data-notrim 属性（此属性暂只允许添加在文本框上，与 serializeObject() 匹配），则前后空格也参与验证。
 * @type object
 * @attr {object} messages 验证不通过时的提示
 *      required: '此字段必填'，当文本框上定义了 data-notrim，则功能与 requiredNoTirm 相同
 *      requiredNoTrim: '此字段必填'，允许只填写空格（兼容之前的版本，推荐使用 required 配合 data-notrim 实现）
 *      number: '此字段必须为数字'
 *      numberRange: '此字段的数字范围是：{0}-{1}'
 *      int: '此字段必须为整数'
 *      maxlength: '此字段值最多{0}个字符'
 *      length: '此字段值为{0}个字符'
 *      ZhStrMaxLength: '此字段最多{0}个字符（中文计为2个字符）'
 *      ZhStrRangeLength: '此字段限制{0}-{1}个字符（中文计为2个字符）'
 *      isPhone: '电话号码格式错误'
 *      isCardNo: '身份证号格式错误'
 *      regularName: '此字段只能由字母、数字、下划线组成'
 *      email: '电子邮件格式不正确'
 *      postalCode: '邮政编码格式不正确'
 * @attr {object} methods 验证规则时的操作
 * @attr {function} add 添加自定义验证规则
 *   function(ruleName,ruleMethod,msg)
 */
$.validator = {
    messages: {
        required: '此字段必填',
        requiredNoTrim: '此字段必填',
        number: '此字段必须为数字',
        numberRange: '此字段必须为数字，范围：{0}~{1}',
        int: '此字段必须为整数',
        maxlength: '此字段值最多{0}个字符',
        length: '此字段值为{0}个字符',
        ZhStrMaxLength: '此字段最多{0}个字符（中文计为2个字符）',
        ZhStrRangeLength: '此字段限制{0}-{1}个字符（中文计为2个字符）',
        isPhone: '电话号码格式错误',
        isCardNo: '身份证号格式错误',
        regularName: '此字段只能由字母、数字、下划线组成',
        email: '电子邮件格式不正确',
        postalCode: '邮政编码格式不正确'
    },
    // 验证通过时返回 true，不通过时返回 false
    methods: {
        required: function(limit, el){
            if(limit){
                var val = el.val();
                if(typeof el.attr('data-notrim') == 'undefined'){// 若定义了 data-notrim 属性，则前后空格参与验证
                    val = val.trim();
                }
                return val && val.length > 0;
            }
            return true;
        },
        // 必填，允许只填写空格
        requiredNoTrim: function(limit, el){
            if(limit){
                var val = el.val();
                return val && val.length > 0;
            }
            return true;
        },
        number: function(limit, el){
            if(limit){
                var val = el.val();
                if(typeof el.attr('data-notrim') == 'undefined'){// 若定义了 data-notrim 属性，则前后空格参与验证
                    val = val.trim();
                }
                return !val || /^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/.test(val);
            }
            return true;
        },
        // 数字范围验证，值必须为数字
        numberRange: function(limit, el){
            if(limit.constructor == Array){
                var val = el.val(),
                    min = limit[0],
                    max = limit[1];
                if(typeof el.attr('data-notrim') == 'undefined'){// 若定义了 data-notrim 属性，则前后空格参与验证
                    val = val.trim();
                }
                if(val){
                    if(typeof min == 'undefined'){
                        limit[0] = '不限';
                    }
                    if(typeof max == 'undefined'){
                        limit[1] = '不限';
                    }
                    if(/^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/.test(val)){// 非空，首先验证数字，同 number 的规则
                        val = Number(val);// 转换为数字
                        if(typeof min != 'undefined' && val < min ||// 定义了最小值，但不符合
                            typeof max != 'undefined' && val > max){// 定义了最大值，但不符合
                            return false;
                        }
                    }
                    else{// 有值，但是非数字
                        return false;
                    }
                }
            }
            return true;
        },
        int: function(limit, el){
            if(limit){
                var val = el.val();
                if(typeof el.attr('data-notrim') == 'undefined'){// 若定义了 data-notrim 属性，则前后空格参与验证
                    val = val.trim();
                }
                return !val || /^-?\d+$/.test(val);
            }
            return true;
        },
        maxlength: function(limit, el){
            if(typeof limit == 'number'){
                var val = el.val();
                if(typeof el.attr('data-notrim') == 'undefined'){// 若定义了 data-notrim 属性，则前后空格参与验证
                    val = val.trim();
                }
                return !val || val.length <= limit;
            }
            return true;
        },
        length: function(limit, el){
            if(typeof limit == 'number'){
                var val = el.val();
                if(typeof el.attr('data-notrim') == 'undefined'){// 若定义了 data-notrim 属性，则前后空格参与验证
                    val = val.trim();
                }
                return !val || val.length == limit;
            }
            return true;
        },
        // 字符最大长度验证（一个中文字符长度为2）
        ZhStrMaxLength: function(limit, el){
            if(typeof limit == 'number'){
                var val = el.val();
                if(typeof el.attr('data-notrim') == 'undefined'){// 若定义了 data-notrim 属性，则前后空格参与验证
                    val = val.trim();
                }
                return !val || $.getZhStrLength(val) <= limit;
            }
            return true;
        },
        // 字符长度区间验证（一个中文字符长度为2）不能在用class属性定义验证规则时使用,取不到区间的值
        ZhStrRangeLength: function(limit, el){
            if(limit.constructor == Array){
                var val = el.val()
                    , length = $.getZhStrLength(val);
                if(typeof el.attr('data-notrim') == 'undefined'){// 若定义了 data-notrim 属性，则前后空格参与验证
                    val = val.trim();
                }
                return !val || (length >= limit[0] && length <= limit[1]);
            }
            return true;
        },
        // 联系电话(手机/电话皆可)验证
        isPhone: function(limit, el){
            if(limit){
                var val = el.val()
                    , mobileRex = /^1\d{10}$/
                    , telRex = /^(0[0-9]{2,3}\-?)?([2-9][0-9]{6,7})+(\-[0-9]{1,4})?$/;
                if(typeof el.attr('data-notrim') == 'undefined'){// 若定义了 data-notrim 属性，则前后空格参与验证
                    val = val.trim();
                }
                return !val || (telRex.test(val) || (val.length == 11 && mobileRex.test(val)));
            }
            return true;
        },
        // 身份证号码为15位或者18位，15位时全为数字，18位前17位为数字，最后一位是校验位，可能为数字或字符X
        isCardNo: function(limit, el){
            var _cardNoVali = function(idcard){
                idcard = idcard.toString().toUpperCase();// 将末位的x装换成X
                // 身份证号码为15位或者18位，15位时全为数字，18位前17位为数字，最后一位是校验位，可能为数字或字符X
                if(!(/(^\d{15}$)|(^\d{17}([0-9]|X)$)/i.test(idcard))) return false;
                var paritybit = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];// 校验位取值
                var power_list = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];// 加权因子

                var fifteenToEighteen = function(str){
                    var s = 0;
                    var newid = str.substring(0, 6) + "19" + str.substring(6, str.length);
                    for(var i = 0; i < newid.length; i++){
                        s += parseInt(newid.substring(i, i + 1), 10) * power_list[i];
                    }
                    return newid + paritybit[s % 11];
                };
                /**验证1位校验码（18位）*/
                var checkcodeValidation = function(str){
                    for(var i = 0, s = 0; i < str.length - 1; i++){
                        s += parseInt(str[i], 10) * power_list[i];
                    }
                    return paritybit[s % 11] == str[17];
                };
                /**验证6位地址码（前6位）? 2位*/
                var locationValidation = function(str){
                    var provincesAndCities = ['11', '12', '13', '14', '15', '21', '22',
                        '23', '31', '32', '33', '34', '35', '36',
                        '37', '41', '42', '43', '44', '45', '46',
                        '50', '51', '52', '53', '54', '61', '62',
                        '63', '64', '65', '71', '81', '82', '91'];
                    /**省、直辖市代码*/
                    return provincesAndCities.indexOf(str) != -1;
                };
                /**验证8位生日数字（7到14位）*/
                var birthdayValidation = function(str){
                    var year = str.substring(0, 4);
                    var month = str.substring(4, 6);
                    var day = str.substring(6, 8);
                    var birthday = year + "/" + month + "/" + day;
                    //var date = new Date(year,parseInt(month, 10)-1,day);// ie8 下 parseInt() 默认基数为8， 08,09 会变成 0
                    var date = new Date(birthday);
                    /**大于等于当前日期 或 小于1900年1月1日*/
                    if(date >= new Date() || date <= new Date(1900, 0, 1)) return false;
                    return date.format("yyyy/MM/dd") == birthday;
                };
                if(15 == idcard.length){// 15位转18位
                    idcard = fifteenToEighteen(idcard);
                }
                return (locationValidation(idcard.substring(0, 2))// 验证6位地址码（前6位）? 2位
                && birthdayValidation(idcard.substring(6, 14))// 验证8位生日数字（7到14位）
                && checkcodeValidation(idcard));// 验证1位校验码（18位）
            };
            if(limit){
                var val = el.val();
                if(typeof el.attr('data-notrim') == 'undefined'){// 若定义了 data-notrim 属性，则前后空格参与验证
                    val = val.trim();
                }
                return !val || _cardNoVali(val);
            }
            return true;
        },
        regularName: function(limit, el){
            if(limit){
                var val = el.val()
                    , cardNoRex = /(^[\da-zA-Z_]+$)/;
                if(typeof el.attr('data-notrim') == 'undefined'){// 若定义了 data-notrim 属性，则前后空格参与验证
                    val = val.trim();
                }
                return !val || cardNoRex.test(val);
            }
            return true;
        },
        // 电子邮件
        email: function(limit, el){
            if(limit){
                var val = el.val(),
                //email = /^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/;
                    email = /^[a-zA-Z\d][-\.\w]*@(?:[-\w]+\.)+(?:[a-zA-Z])+$/;// 20170713 modified by qq from taobao
                if(typeof el.attr('data-notrim') == 'undefined'){// 若定义了 data-notrim 属性，则前后空格参与验证
                    val = val.trim();
                }
                return !val || email.test(val);
            }
            return true;
        },
        // 邮政编码
        postalCode: function(limit, el){
            if(limit){
                var val = el.val(),
                    PostalCode = /^\d{6}$/;
                if(typeof el.attr('data-notrim') == 'undefined'){// 若定义了 data-notrim 属性，则前后空格参与验证
                    val = val.trim();
                }
                return !val || PostalCode.test(val);
            }
            return true;
        }
    },
    /**
     * 扩展验证对象
     * @param ruleName {string} 规则名
     * @param ruleMethod {function} 验证方法
     * @param msg {string} 默认提示信息
     */
    add: function(ruleName, ruleMethod, msg){
        $.validator.messages[ruleName] = msg;
        $.validator.methods[ruleName] = ruleMethod;
    }
};